<template>
  <Menu
    :selectedKeys="menuState.selectedKeys"
    :defaultSelectedKeys="menuState.defaultSelectedKeys"
    :mode="mode"
    :openKeys="getOpenKeys"
    :inlineIndent="inlineIndent"
    :theme="theme"
    @open-change="handleOpenChange"
    :class="getMenuClass"
    @click="handleMenuClick"
    :subMenuOpenDelay="0.2"
    v-bind="getInlineCollapseOptions"
  >
    <template v-for="item in items" :key="item.path">
      <BasicSubMenuItem :item="item" :theme="theme" :isHorizontal="isHorizontal" />
    </template>
  </Menu>
</template>
<script lang="ts" setup>
  import type { MenuState } from './types';
  import { computed, unref, reactive, watch, toRefs, ref } from 'vue';
  import { Menu, MenuProps } from 'ant-design-vue';
  import BasicSubMenuItem from './components/BasicSubMenuItem.vue';
  import { MenuModeEnum, MenuTypeEnum } from '@/enums/menuEnum';
  import { useOpenKeys } from './useOpenKeys';
  import { RouteLocationNormalizedLoaded, useRouter } from 'vue-router';
  import { isFunction } from '@/utils/is';
  import { basicProps } from './props';
  import { useMenuSetting } from '@/hooks/setting/useMenuSetting';
  import { REDIRECT_NAME } from '@/router/constant';
  import { useDesign } from '@/hooks/web/useDesign';
  import { getCurrentParentPath } from '@/router/menus';
  import { listenerRouteChange } from '@/logics/mitt/routeChange';
  import { getAllParentPath } from '@/router/helper/menuHelper';

  defineOptions({ name: 'BasicMenu' });

  const props = defineProps(basicProps);

  const emit = defineEmits(['menuClick']);

  const isClickGo = ref(false);
  const currentActiveMenu = ref('');

  const menuState = reactive<MenuState>({
    defaultSelectedKeys: [],
    openKeys: [],
    selectedKeys: [],
    collapsedOpenKeys: [],
  });

  const { prefixCls } = useDesign('basic-menu');
  const { items, mode, accordion } = toRefs(props);

  const { getCollapsed, getTopMenuAlign, getSplit } = useMenuSetting();

  const { currentRoute } = useRouter();

  const { handleOpenChange, setOpenKeys, getOpenKeys } = useOpenKeys(
    menuState,
    items,
    mode as any,
    accordion,
  );

  const getIsTopMenu = computed(() => {
    const { type, mode } = props;

    return (
      (type === MenuTypeEnum.TOP_MENU && mode === MenuModeEnum.HORIZONTAL) ||
      (props.isHorizontal && unref(getSplit))
    );
  });

  const getMenuClass = computed(() => {
    const align = props.isHorizontal && unref(getSplit) ? 'start' : unref(getTopMenuAlign);
    return [
      prefixCls,
      `justify-${align}`,
      {
        [`${prefixCls}__second`]: !props.isHorizontal && unref(getSplit),
        [`${prefixCls}__sidebar-hor`]: unref(getIsTopMenu),
      },
    ];
  });

  const getInlineCollapseOptions = computed(() => {
    const isInline = props.mode === MenuModeEnum.INLINE;

    const inlineCollapseOptions: { inlineCollapsed?: boolean } = {};
    if (isInline) {
      inlineCollapseOptions.inlineCollapsed = props.mixSider ? false : unref(getCollapsed);
    }
    return inlineCollapseOptions;
  });

  listenerRouteChange((route) => {
    if (route.name === REDIRECT_NAME) return;
    handleMenuChange(route);
    currentActiveMenu.value = route.meta?.currentActiveMenu as string;

    if (unref(currentActiveMenu)) {
      menuState.selectedKeys = [unref(currentActiveMenu)];
      setOpenKeys(unref(currentActiveMenu));
    }
  });

  !props.mixSider &&
    watch(
      () => props.items,
      () => {
        handleMenuChange();
      },
    );

  const handleMenuClick: MenuProps['onClick'] = async ({ key }) => {
    const { beforeClickFn } = props;
    if (beforeClickFn && isFunction(beforeClickFn)) {
      const flag = await beforeClickFn(key);
      if (!flag) return;
    }
    emit('menuClick', key);

    isClickGo.value = true;
    menuState.selectedKeys = [key];
  };

  async function handleMenuChange(route?: RouteLocationNormalizedLoaded) {
    if (unref(isClickGo)) {
      isClickGo.value = false;
      return;
    }
    const path =
      (route || unref(currentRoute)).meta?.currentActiveMenu || (route || unref(currentRoute)).path;
    setOpenKeys(path);
    if (unref(currentActiveMenu)) return;
    if (props.isHorizontal && unref(getSplit)) {
      const parentPath = await getCurrentParentPath(path);
      menuState.selectedKeys = [parentPath];
    } else {
      const parentPaths = await getAllParentPath(props.items, path);
      menuState.selectedKeys = parentPaths;
    }
  }
</script>
<style lang="less">
  @import url('./index.less');
</style>
